// Copyright 2008 Shing Hing Man
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language
// governing permissions and limitations under the License.

package it.infodea.tapestrydea.components;

import java.util.HashMap;
import java.util.Iterator;

import org.apache.tapestry5.Asset;
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ClientElement;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.RenderSupport;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.IncludeJavaScriptLibrary;
import org.apache.tapestry5.annotations.IncludeStylesheet;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.annotations.Retain;
import org.apache.tapestry5.annotations.SupportsInformalParameters;
import org.apache.tapestry5.ioc.annotations.Inject;

/**
 * This component is wrapper around the syntaxhighter (version 1.5.1) by
 * alex.gorbatchev at http://code.google.com/p/syntaxhighlighter/.
 * 
 * @author Shing Hing Man
 * 
 */
@SupportsInformalParameters
@IncludeJavaScriptLibrary(value = { "${dea.jsscripts}/syntaxhighlighter/shCore.js", "${dea.jsscripts}/syntaxhighlighter/shBrushCss.js",
		"${dea.jsscripts}/syntaxhighlighter/clipboard.js" })
@IncludeStylesheet(value = "../assets/styles/syntaxHighlighter.css")
public class SyntaxHighlighterDea implements ClientElement {

	/**
	 * One between these: java, xml, html, xhtml, xslt, js, jscript, javascript, css, sql.
	 * By default html.
	 */
	@Parameter(value = "html", defaultPrefix = BindingConstants.LITERAL)
	private String language;

	@Environmental
	private RenderSupport support;

	@Inject
	private ComponentResources resources;

	@Inject
	@Path("${dea.jsscripts}/syntaxhighlighter/shBrushJava.js")
	private Asset shBrushJava;

	@Inject
	@Path("${dea.jsscripts}/syntaxhighlighter/shBrushXml.js")
	private Asset shBrushXml;

	@Inject
	@Path("${dea.jsscripts}/syntaxhighlighter/shBrushJScript.js")
	private Asset shBrushJScript;

	@Inject
	@Path("${dea.jsscripts}/syntaxhighlighter/shBrushCss.js")
	private Asset shBrushCss;

	@Inject
	@Path("${dea.jsscripts}/syntaxhighlighter/shBrushSql.js")
	private Asset shBrushSql;

	private String clientId;

	@Retain
	private HashMap<String, Asset> codeToScriptMap = new HashMap<String, Asset>();

	protected void beginRender(MarkupWriter writer) {
		if (!codeToScriptMap.containsKey(language)) {
			throw new RuntimeException("The following lanuage is not supported : " + language + "\n Supported lanuages are :" + getKeys());

		}
		support.addScriptLink(codeToScriptMap.get(language));
		clientId = support.allocateClientId(resources.getId());
		writer.element("pre", "name", clientId, "class", language);
		resources.renderInformalParameters(writer);
	}

	protected void afterRender(MarkupWriter writer) {
		writer.end(); //pre
		support.addScript("dp.SyntaxHighlighter.HighlightAll('%s');", clientId);
	}

	void pageLoaded() {
		codeToScriptMap = new HashMap<String, Asset>();
		codeToScriptMap.put("java", shBrushJava);
		codeToScriptMap.put("xml", shBrushXml);
		codeToScriptMap.put("html", shBrushXml);
		codeToScriptMap.put("xhtml", shBrushXml);
		codeToScriptMap.put("xslt", shBrushXml);
		codeToScriptMap.put("js", shBrushJScript);
		codeToScriptMap.put("jscript", shBrushJScript);
		codeToScriptMap.put("javascript", shBrushJScript);
		codeToScriptMap.put("css", shBrushCss);
		codeToScriptMap.put("sql", shBrushSql);
	}

	public String getClientId() {
		return clientId;
	}

	public String getKeys() {
		Iterator<String> it = codeToScriptMap.keySet().iterator();
		StringBuffer sb = new StringBuffer();
		while (it.hasNext()) {
			sb.append(it.next()).append(",");
		}

		return sb.toString();
	}
}
